package com.xique.park.utils;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.xique.common.core.domain.R;
import com.xique.common.core.utils.StringUtils;
import com.xique.common.core.utils.json.JSONObject;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.common.redis.service.RedisService;
import com.xique.park.api.IWechatClientApi;
import com.xique.park.bean.domain.wechat.WeixinCode2Session;
import com.xique.park.constant.message.LaneDtConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author shd
 * @create 2022/4/13 20:29
 */
@Component
@Slf4j
public class WechatUtils {

    @Autowired
    private IWechatClientApi wxClientApi;

    @Autowired
    private RedisService redisService;

    private final static String PREFIX = "wx:";

    private R<String> getAccessToken(String appId, String secret) {

        String accessToken = redisService.getCacheObject(PREFIX + appId);

        if (StringUtils.isNotEmpty(accessToken)) {
            return R.ok(accessToken);
        }

        Map<String, Object> params = new HashMap<>(3);
        params.put("appid", appId);
        params.put("secret", secret);
        params.put("grant_type", "client_credential");
        log.info("access_token请求参数：{}", params);

        JSONObject result = wxClientApi.getAccessToken(params);
        log.info("access_token返回结果：{}", result);

        if (StringUtils.isEmpty(result)) {
            return R.fail("微信未返回消息");
        }

        if (StringUtils.isNotNull(result.getInt("errcode")) && 0 != result.getInt("errcode")) {
            return R.fail(result.getStr("errmsg"));
        }

        accessToken = result.getStr("access_token");
        Long expiresIn = result.getLong("expires_in");

        redisService.setCacheObject(PREFIX + appId, accessToken, expiresIn, TimeUnit.SECONDS);

        return R.ok(accessToken);
    }

    public R<String> getPhone(String appId, String secret, String code) {
        if (StringUtils.isEmpty(code)) {
            return R.fail("code不能为空");
        }
        R<String> result = getAccessToken(appId, secret);
        if (R.FAIL == result.getCode()) {
            return R.fail(result.getMsg());
        }
        Map<String, Object> params = new HashMap<>(2);
        params.put("access_token", result.getData());
        params.put("code", code);
        log.info("getPhone请求参数：{}", params);

        JSONObject wxResult = wxClientApi.getPhone(Collections.singletonMap("access_token", result.getData()), Collections.singletonMap("code", code));
        log.info("getPhone返回结果：{}", wxResult);

        if (StringUtils.isEmpty(wxResult)) {
            return R.fail("微信未返回消息");
        }

        if (StringUtils.isNotNull(wxResult.getInt("errcode")) && 0 != wxResult.getInt("errcode")) {
            return R.fail(wxResult.getStr("errmsg"));
        }

        JSONObject phoneInfo = wxResult.getObj("phone_info");
        String phoneNumber = phoneInfo.getStr("phoneNumber");

        return R.ok(phoneNumber);
    }

    public R<WeixinCode2Session> getCode2Session(String appId, String secret, String code) {
        if (StringUtils.isEmpty(code)) {
            return R.fail("code不能为空");
        }
        Map<String, Object> params = new HashMap<>(4);
        params.put("appid", appId);
        params.put("secret", secret);
        params.put("js_code", code);
        params.put("grant_type", "authorization_code");
        log.info("jscode2Session请求参数：{}", params);

        JSONObject result = wxClientApi.jscode2session(params);
        log.info("jscode2Session返回结果：{}", result);

        if (StringUtils.isEmpty(result)) {
            return R.fail("微信未返回消息");
        }

        if (StringUtils.isNotNull(result.getInt("errcode")) && 0 != result.getInt("errcode")) {
            return R.fail(result.getStr("errmsg"));
        }

        WeixinCode2Session session = new WeixinCode2Session();
        session.setOpenId(result.getStr("openid"));
        session.setSessionKey(result.getStr("session_key"));
        session.setUnionId(StrUtil.isEmpty(result.getStr("unionid")) ? null : result.getStr("unionid"));

        return R.ok(session);
    }

    public AjaxResult sendMessage(String appId, String secret, String touser, String templateId,
                                  String url, Map<String, Object> miniprogram,
                                  com.alibaba.fastjson.JSONObject data) {
        R<String> result = getAccessToken(appId, secret);
        if (R.FAIL == result.getCode()) {
            return AjaxResult.error(result.getMsg());
        }
        Map<String, Object> params = new HashMap<>(3);
        params.put("touser", touser);
        params.put("template_id", templateId);
        params.put("url", url);
        params.put("miniprogram", miniprogram);
        params.put("data", data);
        log.info("订阅消息推送参数：{}", params);

        JSONObject wxResult = wxClientApi.bizsend(Collections.singletonMap("access_token", result.getData()), params);
        log.info("订阅消息推送结果：{}", wxResult);

        if (StringUtils.isEmpty(wxResult)) {
            return AjaxResult.error("微信未返回消息");
        }

        if (StringUtils.isNotNull(wxResult.getInt("errcode")) && 0 != wxResult.getInt("errcode")) {
            return AjaxResult.error(JSONObject.valueAsStr(wxResult));
        }

        return AjaxResult.success();
    }

    public AjaxResult sendMessageV1(String appId, String secret, Map<String, Object> params) {
        R<String> result = getAccessToken(appId, secret);
        if (R.FAIL == result.getCode()) {
            return AjaxResult.error(result.getMsg());
        }
//        log.info("订阅消息推送参数：{}", params);
        JSONObject wxResult = wxClientApi.bizsend(Collections.singletonMap("access_token", result.getData()), params);
//        log.info("订阅消息推送结果：{}", wxResult);

        if (StringUtils.isEmpty(wxResult)) {
            return AjaxResult.error("微信未返回消息");
        }

        if (StringUtils.isNotNull(wxResult.getInt("errcode")) && 0 != wxResult.getInt("errcode")) {
            log.error("订阅消息推送失败结果：{}", JSONUtil.toJsonStr(wxResult));
            return AjaxResult.error(JSONObject.valueAsStr(wxResult));
        }

        return AjaxResult.success();
    }

    /**
     * 获取小程序分享码的照片
     * @param appid
     * @param secret
     * @param parkId
     * @param laneId
     * @return
     */
    public  InputStream getMiniQrcodePic(String appid,String secret, Long parkId, Long laneId) {
        R<String> result = getAccessToken(appid, secret);
        if (R.FAIL == result.getCode()) {
            return null;
        }
        try {
            URL url = new URL("https://api.weixin.qq.com/wxa/getwxacode?access_token=" + result.getData());
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            //post 必须 post
            httpURLConnection.setRequestMethod("POST");
            // 发送POST请求必须设置如下两行
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
            // 发送请求参数
            JSONObject paramJson = new JSONObject();
            //这就是你二维码里携带的参数
            paramJson.put("scene", "parkId=" + parkId + "laneId=" + laneId);
            //这是设置扫描二维码后跳转的页面
            paramJson.put("page", "pages/index/index");
            printWriter.write(paramJson.toString());
            // flush输出流的缓冲
            printWriter.flush();
            return httpURLConnection.getInputStream();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取小程序分享码的链接
     * @param appid
     * @param secret
     * @param parkId
     * @param laneId
     * @return
     */
    public  String getMiniQrcodeLink(String appid,String secret, Long parkId,Long laneId,Integer laneType) {
        R<String> accessToken = getAccessToken(appid, secret);
        if (R.FAIL == accessToken.getCode()) {
            return null;
        }
        JSONObject paramMap = new JSONObject();
        //通过 URL Link 进入的小程序页面路径，必须是已经发布的小程序存在的页面，不可携带 query 。path 为空时会跳转小程序主页
        String path  = "";
        if (LaneDtConstants.LANE_TYPE_IN.equals(laneType) || LaneDtConstants.LANE_TYPE_BOTH.equals(laneType)){
//            path="pages/index/inpark";
            path="pages/visitor/visitor";
        }else if (LaneDtConstants.LANE_TYPE_OUT.equals(laneType)){
            path="pages/index/outpark";
        }
        paramMap.put("path", path);
        //小程序页面的参数，直接为：参数=值
        paramMap.put("query", "parkId=" + parkId + "&laneId=" + laneId);
        //生成的 URL Link 类型，到期失效：true，永久有效：false
        paramMap.put("is_expire", false);
        String generateLinkUrl = "https://api.weixin.qq.com/wxa/generate_urllink?access_token=ACCESS_TOKEN";
        String postUrl = generateLinkUrl.replaceAll("ACCESS_TOKEN", accessToken.getData());
        String result = HttpUtil.post(postUrl, paramMap.toString());
        System.out.println(result);
        com.alibaba.fastjson.JSONObject jsonObject =  com.alibaba.fastjson.JSONObject.parseObject(result);
        String wxUrl = jsonObject.getString("url_link");
        return wxUrl;

    }
}
